﻿Imports System
Imports System.IO
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary
''' <summary>
''' 1条线源。每一条线源由多个顶点构成。
''' </summary>
''' <remarks></remarks>
<Serializable()> Public Class Line
    Inherits BaseSource
    Implements ICloneable
    Private m_ArrayVolumeSourceLocation(-1) As Location   '用体源来模拟线源数组的数组的坐标
    Private m_ArrayVolumeSource(-1) As VolumeSource  '用体源来模拟线源数组的数组
    Private m_LinePoints(-1) As Point3D '用于储存线源的顶点的数组。数组的第一个点为线源的起点。
    Private m_Width As Double = 10 '用于储存线源的宽度
    Private m_Length As Double  '用于储存线的倍数。暂时不用这个参数




    ''' <summary>
    ''' 线源的垂向长，
    ''' </summary>
    ''' <remarks></remarks>
    Private m_Height As Double = 4
    ''' <summary>
    ''' 线源的有效高度，m
    ''' </summary>
    ''' <remarks></remarks>
    Private m_Relhgt As Double = 2
    Private m_PolluteUnit As String = "g/s•m"  '污染物排放速率单位
    ''' <summary>
    ''' 用体源来模拟线源数组的数组的坐标
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property ArrayVolumeSourceLocation() As Location()
        Get
            Return Me.m_ArrayVolumeSourceLocation
        End Get
        Set(ByVal value As Location())
            Me.m_ArrayVolumeSourceLocation = value
        End Set
    End Property
    ''' <summary>
    ''' 线源数组的数组。每一条线源由若干个面源组成
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property ArrayVolumeSource() As VolumeSource()
        Get
            Return Me.m_ArrayVolumeSource
        End Get
        Set(ByVal value As VolumeSource())
            Me.m_ArrayVolumeSource = value
        End Set
    End Property
    ''' <summary>
    ''' 用于储存线源的数组
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property LinePoints() As Point3D() '
        Get
            Return Me.m_LinePoints
        End Get
        Set(ByVal value As Point3D())
            Me.m_LinePoints = value
        End Set
    End Property
    ''' <summary>
    ''' 用于储存线源的宽度
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property Width() As Double '
        Get
            Return Me.m_Width
        End Get
        Set(ByVal value As Double)
            Me.m_Width = value
        End Set
    End Property
    ''' <summary>
    ''' 用于储存线的倍数
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property Length() As Double '
        Get
            Return Me.m_Length
        End Get
        Set(ByVal value As Double)
            Me.m_Length = value
        End Set
    End Property
    ''' <summary>
    ''' 线源的垂向长，
    ''' </summary>
    ''' <remarks></remarks>
    Property Height() As Double
        Get
            Return Me.m_Height
        End Get
        Set(ByVal value As Double)
            Me.m_Height = value
        End Set
    End Property
    ''' <summary>
    ''' 线源的有效高度，m
    ''' </summary>
    ''' <remarks></remarks>
    Property Relhgt() As Double
        Get
            Return Me.m_Relhgt
        End Get
        Set(ByVal value As Double)
            Me.m_Relhgt = value
        End Set
    End Property
    ''' <summary>
    ''' 污染物的单位
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Property PolluteUnit() As String
        Get
            Return m_PolluteUnit
        End Get
        Set(ByVal value As String)
            m_PolluteUnit = value
        End Set
    End Property

    Public Sub New()
        ReDim Me.m_LinePoints(1)
        Me.m_LinePoints(0) = New Point3D
        Me.m_LinePoints(0).x = Me.Location.Xs
        Me.m_LinePoints(0).y = Me.Location.Ys
        Me.m_LinePoints(0).z = Me.Location.Zs

        Me.m_LinePoints(1) = New Point3D
        Me.m_LinePoints(1).x = 500
        Me.m_LinePoints(1).y = 500
        Me.m_LinePoints(1).z = 0

    End Sub
    Public Function GetLineVert() As String
        Dim Vert As String = ""
        For i As Integer = 1 To Me.m_LinePoints.Length - 1
            Vert = Vert & Me.m_LinePoints(i).x & " "
            Vert = Vert & Me.m_LinePoints(i).y & " "
            Vert = Vert & Me.m_LinePoints(i).z & " "
        Next
        Return Vert
    End Function

    Public Sub SetLineVert(ByVal Vert As String)
        Dim nCount As Integer = StringHandle.GetStringNumber(Vert)
        ReDim Preserve Me.m_LinePoints(nCount / 3)

        For i As Integer = 0 To nCount / 3 - 1
            Me.m_LinePoints(i + 1) = New Point3D
            Me.m_LinePoints(i + 1).x = StringHandle.GetString(Vert, i * 3 + 1)
            Me.m_LinePoints(i + 1).y = StringHandle.GetString(Vert, i * 3 + 2)
            Me.m_LinePoints(i + 1).z = StringHandle.GetString(Vert, i * 3 + 3)
        Next
    End Sub

    Public Sub CreateVolumeLocation()
        If Me.m_LinePoints.Length >= 2 Then
            Me.m_LinePoints(0).x = Me.Location.Xs
            Me.m_LinePoints(0).y = Me.Location.Ys
            Me.m_LinePoints(0).z = Me.Location.Zs
        End If
        ReDim Preserve Me.m_ArrayVolumeSourceLocation(-1)
        For i As Integer = 0 To Me.m_LinePoints.Length - 2
            If (m_LinePoints(i).x - m_LinePoints(i + 1).x) ^ 2 + (m_LinePoints(i).y - m_LinePoints(i + 1).y) ^ 2 Then '线段长度不为0
                Dim DLength As Double = Math.Sqrt((m_LinePoints(i).x - m_LinePoints(i + 1).x) ^ 2 + (m_LinePoints(i).y - m_LinePoints(i + 1).y) ^ 2) '求得线段的长度
                Dim multiple As Double = DLength / Me.m_Width '线段是宽度的倍数，用来求每段时每一个体源的X,Y坐标。
                Dim DX As Double = (m_LinePoints(i + 1).x - m_LinePoints(i).x) / multiple  '每一个X段的长度。带正负号
                Dim DY As Double = (m_LinePoints(i + 1).y - m_LinePoints(i).y) / multiple  '每一个Y段的长度。带正负号
                Dim DZ As Double = (m_LinePoints(i + 1).z - m_LinePoints(i).z) / multiple  '每一个Z段的长度。带正负号

                Dim nCount As Integer = Math.Truncate(multiple) '反复线段的个数，不包含最后一段。
                For j As Integer = 0 To nCount - 1 '求得除最后一个以外的所有体源
                    ReDim Preserve Me.m_ArrayVolumeSourceLocation(Me.m_ArrayVolumeSourceLocation.Length) '数组增加1
                    Me.m_ArrayVolumeSourceLocation(Me.m_ArrayVolumeSourceLocation.Length - 1) = New Location
                    '加入体源的坐标
                    Me.m_ArrayVolumeSourceLocation(Me.m_ArrayVolumeSourceLocation.Length - 1).Scrtyp = EnumScrtyp.VOLUME
                    Me.m_ArrayVolumeSourceLocation(Me.m_ArrayVolumeSourceLocation.Length - 1).Srcid = Me.Location.Srcid & "V" & Me.m_ArrayVolumeSourceLocation.Length
                    Me.m_ArrayVolumeSourceLocation(Me.m_ArrayVolumeSourceLocation.Length - 1).Xs = m_LinePoints(i).x + DX / 2 + j * DX
                    Me.m_ArrayVolumeSourceLocation(Me.m_ArrayVolumeSourceLocation.Length - 1).Ys = m_LinePoints(i).y + DY / 2 + j * DY
                    Me.m_ArrayVolumeSourceLocation(Me.m_ArrayVolumeSourceLocation.Length - 1).Zs = m_LinePoints(i).z + DZ / 2 + j * DZ
                Next
                Dim LastLenmultiple As Double = DLength - nCount * m_Width   '最后一段长度
                If Math.Abs(LastLenmultiple) > 0.01 Then
                    ReDim Preserve Me.m_ArrayVolumeSourceLocation(Me.m_ArrayVolumeSourceLocation.Length) '数组增加1
                    Me.m_ArrayVolumeSourceLocation(Me.m_ArrayVolumeSourceLocation.Length - 1) = New Location

                    Me.m_ArrayVolumeSourceLocation(Me.m_ArrayVolumeSourceLocation.Length - 1).Scrtyp = EnumScrtyp.VOLUME
                    Me.m_ArrayVolumeSourceLocation(Me.m_ArrayVolumeSourceLocation.Length - 1).Srcid = Me.Location.Srcid & "V" & Me.m_ArrayVolumeSourceLocation.Length
                    Me.m_ArrayVolumeSourceLocation(Me.m_ArrayVolumeSourceLocation.Length - 1).Xs = m_LinePoints(i).x + nCount * DX + DX / 2 * LastLenmultiple / Me.m_Width
                    Me.m_ArrayVolumeSourceLocation(Me.m_ArrayVolumeSourceLocation.Length - 1).Ys = m_LinePoints(i).y + nCount * DY + DY / 2 * LastLenmultiple / Me.m_Width
                    Me.m_ArrayVolumeSourceLocation(Me.m_ArrayVolumeSourceLocation.Length - 1).Zs = m_LinePoints(i).z + nCount * DZ + DZ / 2 * LastLenmultiple / Me.m_Width
                End If
            End If
        Next
    End Sub
    ''' <summary>
    ''' 根据用户的设置，获取相应的体源的个数。
    ''' </summary>
    ''' <remarks></remarks>
    Public Function GetVolumesCount() As Integer
        Dim AllCount As Integer = 0
        If Me.m_LinePoints.Length >= 2 Then
            Me.m_LinePoints(0).x = Me.Location.Xs
            Me.m_LinePoints(0).y = Me.Location.Ys
            Me.m_LinePoints(0).z = Me.Location.Zs
        End If
        ReDim Preserve Me.m_ArrayVolumeSource(-1)
        For i As Integer = 0 To Me.m_LinePoints.Length - 2
            If (m_LinePoints(i).x - m_LinePoints(i + 1).x) ^ 2 + (m_LinePoints(i).y - m_LinePoints(i + 1).y) ^ 2 > 0 Then '线段长度不为0
                Dim DLength As Double = Math.Sqrt((m_LinePoints(i).x - m_LinePoints(i + 1).x) ^ 2 + (m_LinePoints(i).y - m_LinePoints(i + 1).y) ^ 2) '求得线段的长度
                Dim multiple As Double = DLength / Me.m_Width '线段是宽度的倍数，用来求每段时每一个体源的X,Y坐标。
                Dim nCount As Integer = Math.Truncate(multiple) '反复线段的个数，不包含最后一段。
                AllCount += nCount
                Dim LastLenmultiple As Double = DLength - nCount * m_Width   '最后一段长度
                If Math.Abs(LastLenmultiple) > 0.01 Then
                    AllCount += 1
                End If
            End If
        Next
        Return AllCount
    End Function

    ''' <summary>
    ''' 根据用户的设置，生成相应的体源。
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub CreateVolume()
        If Me.m_LinePoints.Length >= 2 Then
            Me.m_LinePoints(0).x = Me.Location.Xs
            Me.m_LinePoints(0).y = Me.Location.Ys
            Me.m_LinePoints(0).z = Me.Location.Zs
        End If
        ReDim Preserve Me.m_ArrayVolumeSource(-1)
        For i As Integer = 0 To Me.m_LinePoints.Length - 2
            If (m_LinePoints(i).x - m_LinePoints(i + 1).x) ^ 2 + (m_LinePoints(i).y - m_LinePoints(i + 1).y) ^ 2 Then '线段长度不为0
                Dim DLength As Double = Math.Sqrt((m_LinePoints(i).x - m_LinePoints(i + 1).x) ^ 2 + (m_LinePoints(i).y - m_LinePoints(i + 1).y) ^ 2) '求得线段的长度
                Dim multiple As Double = DLength / Me.m_Width '线段是宽度的倍数，用来求每段时每一个体源的X,Y坐标。
                Dim DX As Double = (m_LinePoints(i + 1).x - m_LinePoints(i).x) / multiple  '每一个X段的长度。带正负号
                Dim DY As Double = (m_LinePoints(i + 1).y - m_LinePoints(i).y) / multiple  '每一个Y段的长度。带正负号
                Dim DZ As Double = (m_LinePoints(i + 1).z - m_LinePoints(i).z) / multiple  '每一个Z段的长度。带正负号

                Dim nCount As Integer = Math.Truncate(multiple) '反复线段的个数，不包含最后一段。
                For j As Integer = 0 To nCount - 1 '求得除最后一个以外的所有体源
                    ReDim Preserve Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length) '数组增加1
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1) = New VolumeSource
                    '加入体源的坐标
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).Location.Scrtyp = EnumScrtyp.VOLUME
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).Location.Srcid = Me.Location.Srcid & "V" & Me.m_ArrayVolumeSource.Length
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).Location.Xs = m_LinePoints(i).x + DX / 2 + j * DX
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).Location.Ys = m_LinePoints(i).y + DY / 2 + j * DY
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).Location.Zs = m_LinePoints(i).z + DZ / 2 + j * DZ
                    '体源的宽度、垂边长、有效高度
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).Width = Me.m_Width
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).Height = Me.Height
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).Relhgt = Me.Relhgt
                    '排放速率
                    ReDim Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).PollutionPara(Me.m_PollutionPara.Length - 1)
                    For n As Integer = 0 To Me.m_PollutionPara.Length - 1
                        Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).PollutionPara(n) = New PollutionPara
                        Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).PollutionPara(n) = Me.m_PollutionPara(n).Clone
                        Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).PollutionPara(n).Name = Me.m_PollutionPara(n).Name
                        Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).PollutionPara(n).Ptemis = Me.m_PollutionPara(n).Ptemis * Me.m_Width
                    Next

                    '小杨，小时变化速率
                    If Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).IsSourceHour = True Then
                        For n As Integer = 0 To Me.m_PollutionPara.Length - 1
                            For jj As Integer = 0 To 8783
                                Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).PollutionPara(n).HourEmisCollection.Add(Me.m_PollutionPara(n).HourEmisCollection.Item(jj))
                            Next
                        Next
                    End If




                    '城市影响
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).Urbansrc = Me.m_Urbansrc.Clone
                    '排放速率变化
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).EmisFact = Me.m_EmisFact.Clone
                    '指定污染源NO2的排放比例
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).NO2Ratio = Me.m_NO2Ratio.Clone

                Next
                Dim LastLenmultiple As Double = DLength - nCount * m_Width   '最后一段长度
                If Math.Abs(LastLenmultiple) > 0.01 Then
                    ReDim Preserve Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length) '数组增加1
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1) = New VolumeSource

                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).Location.Scrtyp = EnumScrtyp.VOLUME
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).Location.Srcid = Me.Location.Srcid & "V" & Me.m_ArrayVolumeSource.Length
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).Location.Xs = m_LinePoints(i).x + nCount * DX + DX / 2 * LastLenmultiple / Me.m_Width
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).Location.Ys = m_LinePoints(i).y + nCount * DY + DY / 2 * LastLenmultiple / Me.m_Width
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).Location.Zs = m_LinePoints(i).z + nCount * DZ + DZ / 2 * LastLenmultiple / Me.m_Width
                    '体源的宽度、垂边长、有效高度
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).Width = Me.m_Width
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).Height = Me.Height
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).Relhgt = Me.Relhgt
                    '排放速率
                    ReDim Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).PollutionPara(Me.m_PollutionPara.Length - 1)
                    For n As Integer = 0 To Me.m_PollutionPara.Length - 1
                        Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).PollutionPara(n) = New PollutionPara
                        Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).PollutionPara(n) = Me.m_PollutionPara(n).Clone
                        Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).PollutionPara(n).Name = Me.m_PollutionPara(n).Name
                        Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).PollutionPara(n).Ptemis = Me.m_PollutionPara(n).Ptemis * LastLenmultiple
                    Next
                    '城市影响
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).Urbansrc = Me.m_Urbansrc.Clone
                    '排放速率变化
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).EmisFact = Me.m_EmisFact.Clone
                    '指定污染源NO2的排放比例
                    Me.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1).NO2Ratio = Me.m_NO2Ratio.Clone
                End If
            End If
        Next

        '把之前计算得到的坐标传给数组
        For j As Integer = 0 To Me.m_ArrayVolumeSourceLocation.Length - 1 '求得除最后一个以外的所有体源
            Me.m_ArrayVolumeSource(j).Location = Me.m_ArrayVolumeSourceLocation(j).Clone
        Next
    End Sub
    ''' <summary>
    ''' 清空相应的体源。主要目的是节约空间
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub ClearVolume()
        Me.ArrayVolumeSource = Nothing
    End Sub
    ''' <summary>
    ''' 根据污染源污染物的名称返回相应的排放速率
    ''' </summary>
    ''' <param name="name">污染物的名称</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetRate(ByVal name As String) As Decimal
        If Me.m_PollutionPara IsNot Nothing AndAlso Me.m_PollutionPara.Length > 0 Then
            For i As Integer = 0 To Me.m_PollutionPara.Length - 1
                If Me.m_PollutionPara(i).Name = name Then
                    Return Me.m_PollutionPara(i).Ptemis
                End If
            Next
        End If
    End Function

    Public Function Clone() As Object Implements System.ICloneable.Clone
        Dim obj As New Line
        obj.m_Location = Me.m_Location.Clone   '污染源的位置等参数
        ReDim obj.PollutionPara(Me.m_PollutionPara.Length - 1) '污染物名称和排放速率。因为同一排放源，其污染物不一样，则排放速率不一样。
        For i As Integer = 0 To Me.m_PollutionPara.Length - 1
            obj.PollutionPara(i) = Me.m_PollutionPara(i).Clone
        Next
        obj.m_SourceName = Me.m_SourceName  '污染源的名称
        obj.m_Urbansrc = Me.m_Urbansrc.Clone '考虑城市影响
        obj.m_EmisFact = Me.m_EmisFact.Clone  '排放速率变化
        obj.m_NowPolluteID = Me.m_NowPolluteID  '表示当前选择的污染物
        obj.m_NO2Ratio = Me.m_NO2Ratio.Clone  '指定污染源NO2的排放比例

        If Me.m_ArrayVolumeSource IsNot Nothing Then
            ReDim obj.m_ArrayVolumeSource(Me.m_ArrayVolumeSource.Length - 1)
            For i As Integer = 0 To Me.m_ArrayVolumeSource.Length - 1
                obj.m_ArrayVolumeSource(i) = Me.m_ArrayVolumeSource(i).Clone
            Next

        End If
        If Me.m_ArrayVolumeSourceLocation IsNot Nothing Then
            ReDim obj.m_ArrayVolumeSourceLocation(Me.m_ArrayVolumeSourceLocation.Length - 1)
            For i As Integer = 0 To Me.m_ArrayVolumeSourceLocation.Length - 1
                obj.m_ArrayVolumeSourceLocation(i) = Me.m_ArrayVolumeSourceLocation(i).Clone
            Next
        End If
        ReDim obj.m_LinePoints(Me.m_LinePoints.Length - 1)
        For i As Integer = 0 To Me.m_LinePoints.Length - 1
            obj.m_LinePoints(i) = Me.m_LinePoints(i).Clone
        Next

        obj.m_Width = Me.m_Width '用于储存线源的宽度
        obj.m_Length = Me.m_Length '用于储存线的倍数
        obj.Height = Me.m_Height
        obj.Relhgt = Me.m_Relhgt
        obj.m_PolluteUnit = Me.m_PolluteUnit

        obj.IsSourceHour = Me.IsSourceHour

        Return obj

    End Function

    <OnDeserializing()> _
Friend Sub OnDeserializingMethod(ByVal context As StreamingContext)

    End Sub

    <OnDeserialized()> _
    Friend Sub OnDeserializedMethod(ByVal context As StreamingContext)
        If Me.m_PolluteUnit Is Nothing Then
            Me.m_PolluteUnit = "g/s•m"
        End If
    End Sub
End Class
